/*
 * Copyright (C) 2025 SDFX Project
 * SDFX is licensed under Mulan PSL v2.
 */

/**
 * @file protocol_handler.c
 * @brief Protocol Handler Module
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>

#include "daemon_internal.h"

/* Device Information */
static DEVICEINFO g_device_info = {
    .IssuerName = "SDFX Project",
    .DeviceName = "SDFX-1.0",
    .DeviceSerial = "SW000001",
    .DeviceVersion = 0x00010000,
    .StandardVersion = 0x00020023,
    .AsymAlgAbility = {0x00000001, 0x00000000},
    .SymAlgAbility = 0x00000401,
    .HashAlgAbility = 0x00000001,
    .BufferSize = 1024 * 1024
};

static int handle_open_device(daemon_context_t *ctx, const sdfx_open_device_req_t *req,
                              sdfx_open_device_resp_t *resp)
{
    LOG_DEBUG("Handling open device request");
    
    uint32_t device_id = device_manager_create_device(ctx);
    if (device_id == 0) {
        return SDR_NOBUFFER;
    }
    
    resp->device_handle = (HANDLE)(uintptr_t)device_id;
    LOG_INFO("Device opened, device_id = %u", device_id);
    return SDR_OK;
}

static int handle_close_device(daemon_context_t *ctx, const sdfx_close_device_req_t *req,
                               sdfx_close_device_resp_t *resp)
{
    LOG_DEBUG("Handling close device request");
    
    uint32_t device_id = (uint32_t)(uintptr_t)req->device_handle;
    int ret = device_manager_validate_device(ctx, device_id);
    if (ret != SDR_OK) {
        return ret;
    }
    
    LOG_INFO("Device closed, device_id = %u", device_id);
    return SDR_OK;
}

static int handle_open_session(daemon_context_t *ctx, const sdfx_open_session_req_t *req,
                               sdfx_open_session_resp_t *resp)
{
    LOG_DEBUG("Handling open session request");
    
    uint32_t device_id = (uint32_t)(uintptr_t)req->device_handle;
    int ret = device_manager_validate_device(ctx, device_id);
    if (ret != SDR_OK) {
        return ret;
    }
    
    uint32_t session_id = session_manager_create_session(ctx, device_id);
    if (session_id == 0) {
        return SDR_NOBUFFER;
    }
    
    resp->session_handle = (HANDLE)(uintptr_t)session_id;
    LOG_INFO("Session opened, session_id = %u, device_id = %u",
             session_id, device_id);
    return SDR_OK;
}

static int handle_close_session(daemon_context_t *ctx, const sdfx_close_session_req_t *req,
                                sdfx_close_session_resp_t *resp)
{
    LOG_DEBUG("Handling close session request");
    
    uint32_t session_id = (uint32_t)(uintptr_t)req->session_handle;
    int ret = session_manager_close_session(ctx, session_id);
    LOG_INFO("Session closed, session_id = %u", session_id);
    return ret;
}

static int handle_get_device_info(daemon_context_t *ctx, const sdfx_get_device_info_req_t *req,
                                  sdfx_get_device_info_resp_t *resp)
{
    LOG_DEBUG("Handling get device info request");
    
    uint32_t session_id = (uint32_t)(uintptr_t)req->session_handle;
    int ret = session_manager_validate_session(ctx, session_id);
    if (ret != SDR_OK) {
        return ret;
    }
    
    memcpy(&resp->device_info, &g_device_info, sizeof(DEVICEINFO));
    return SDR_OK;
}

static int handle_generate_random(daemon_context_t *ctx, const sdfx_generate_random_req_t *req,
                                  sdfx_generate_random_resp_t *resp)
{
    uint32_t session_id = (uint32_t)(uintptr_t)req->session_handle;
    uint32_t length = sdfx_ntohl(req->length);
    
    LOG_DEBUG("Handling generate random request, length = %u", length);
    
    int ret = session_manager_validate_session(ctx, session_id);
    if (ret != SDR_OK) {
        return ret;
    }
    
    /* Enhanced input validation */
    if (length == 0) {
        LOG_ERROR("Random length cannot be zero");
        return SDR_INARGERR;
    }
    if (length > SDFX_MAX_RANDOM_LENGTH) {
        LOG_ERROR("Random length too large: %u bytes (max: %d)", length, SDFX_MAX_RANDOM_LENGTH);
        return SDR_INARGERR;
    }
    
    ret = crypto_generate_random(length, resp->random_data);
    if (ret != SDR_OK) {
        return ret;
    }
    
    resp->length = sdfx_htonl(length);
    LOG_DEBUG("Generated %u bytes of random data", length);
    return SDR_OK;
}

static int handle_hash_init(daemon_context_t *ctx, const sdfx_hash_init_req_t *req,
                           sdfx_hash_init_resp_t *resp)
{
    uint32_t session_id = (uint32_t)(uintptr_t)req->session_handle;
    ULONG alg_id = sdfx_ntohl(req->alg_id);
    
    LOG_DEBUG("Handling hash init request, session_id = %u, alg_id = 0x%lx", 
             session_id, (unsigned long)alg_id);
    
    int ret = session_manager_validate_session(ctx, session_id);
    if (ret != SDR_OK) {
        return ret;
    }
    
    session_info_t *session = session_manager_get_session(ctx, session_id);
    if (session == NULL) {
        return SDR_SESSION_NOT_EXIST;
    }
    
    ret = crypto_hash_init(ctx, session, alg_id);
    if (ret != SDR_OK) {
        LOG_ERROR("Failed to initialize hash: %d", ret);
        session_manager_put_session(session);  /* Release session reference */
        return ret;
    }
    
    session_manager_put_session(session);  /* Release session reference */
    
    LOG_DEBUG("Hash initialized successfully");
    return SDR_OK;
}

static int handle_hash_update(daemon_context_t *ctx, const sdfx_hash_update_req_t *req,
                             sdfx_hash_update_resp_t *resp)
{
    uint32_t session_id = (uint32_t)(uintptr_t)req->session_handle;
    ULONG data_length = sdfx_ntohl(req->data_length);
    
    LOG_DEBUG("Handling hash update request, session_id = %u, data_length = %lu", 
             session_id, (unsigned long)data_length);
    
    int ret = session_manager_validate_session(ctx, session_id);
    if (ret != SDR_OK) {
        return ret;
    }
    
    /* Enhanced input validation */
    if (data_length == 0) {
        LOG_ERROR("Hash data length cannot be zero");
        return SDR_INARGERR;
    }
    if (data_length > SDFX_MAX_MESSAGE_SIZE) {
        LOG_ERROR("Hash data too large: %lu bytes (max: %d)", (unsigned long)data_length, SDFX_MAX_MESSAGE_SIZE);
        return SDR_INARGERR;
    }
    
    session_info_t *session = session_manager_get_session(ctx, session_id);
    if (session == NULL) {
        return SDR_SESSION_NOT_EXIST;
    }
    
    ret = crypto_hash_update(ctx, session, req->data, data_length);
    if (ret != SDR_OK) {
        LOG_ERROR("Failed to update hash: %d", ret);
        session_manager_put_session(session);  /* Release session reference */
        return ret;
    }
    
    session_manager_put_session(session);  /* Release session reference */
    
    LOG_DEBUG("Hash updated successfully");
    return SDR_OK;
}

static int handle_hash_final(daemon_context_t *ctx, const sdfx_hash_final_req_t *req,
                            sdfx_hash_final_resp_t *resp)
{
    uint32_t session_id = (uint32_t)(uintptr_t)req->session_handle;
    
    LOG_DEBUG("Handling hash final request, session_id = %u", session_id);
    
    int ret = session_manager_validate_session(ctx, session_id);
    if (ret != SDR_OK) {
        return ret;
    }
    
    session_info_t *session = session_manager_get_session(ctx, session_id);
    if (session == NULL) {
        return SDR_SESSION_NOT_EXIST;
    }
    
    ULONG hash_length = 64;  // maximum hash length
    ret = crypto_hash_final(ctx, session, resp->hash_data, &hash_length);
    if (ret != SDR_OK) {
        LOG_ERROR("Failed to finalize hash: %d", ret);
        session_manager_put_session(session);  /* Release session reference */
        return ret;
    }
    
    session_manager_put_session(session);  /* Release session reference */
    
    resp->hash_length = sdfx_htonl(hash_length);
    LOG_DEBUG("Hash finalized successfully, length = %lu", (unsigned long)hash_length);
    return SDR_OK;
}

static int handle_encrypt(daemon_context_t *ctx, const sdfx_encrypt_req_t *req,
                         sdfx_encrypt_resp_t *resp)
{
    LOG_DEBUG("Handling encrypt request");
    
    HANDLE session_handle = req->session_handle;
    ULONG alg_id = sdfx_ntohl(req->alg_id);
    ULONG iv_length = sdfx_ntohl(req->iv_length);
    ULONG data_length = sdfx_ntohl(req->data_length);
    
    LOG_DEBUG("Encrypt: session=0x%lx, alg=0x%lx, iv_len=%lu, data_len=%lu", 
             (unsigned long)session_handle, (unsigned long)alg_id, 
             (unsigned long)iv_length, (unsigned long)data_length);
    
    /* Validate session */
    uint32_t session_id = (uint32_t)(uintptr_t)session_handle;
    int ret_validate = session_manager_validate_session(ctx, session_id);
    if (ret_validate != SDR_OK) {
        LOG_ERROR("Invalid session handle: 0x%lx", (unsigned long)session_handle);
        return SDR_SESSION_NOT_EXIST;
    }
    
    /* Extract IV and data */
    const BYTE *iv = (iv_length > 0) ? req->payload : NULL;
    const BYTE *plaintext = req->payload + iv_length;
    
    /* For demonstration purposes, use a fixed key (should be managed by key handle in practice) */
    BYTE key[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
                    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10};
    
    /* Allocate output buffer (reserve enough space for padding) */
    ULONG max_ciphertext_len = data_length + 32; /* 32 bytes padding overhead */
    BYTE *ciphertext = malloc(max_ciphertext_len);
    if (ciphertext == NULL) {
        LOG_ERROR("Failed to allocate ciphertext buffer: %s", strerror(errno));
        return SDR_NOBUFFER;
    }
    
    /* Call symmetric encryption function */
    ULONG ciphertext_len = max_ciphertext_len;
    int result = crypto_symmetric_encrypt(alg_id, key, sizeof(key), iv, iv_length,
                                        plaintext, data_length, ciphertext, &ciphertext_len);
    
    if (result == SDR_OK) {
        /* Convert ciphertext length to network byte order and copy data */
        resp->enc_data_length = sdfx_htonl(ciphertext_len);
        memcpy(resp->enc_data, ciphertext, ciphertext_len);
        LOG_DEBUG("Encryption successful, output length: %lu", (unsigned long)ciphertext_len);
    } else {
        LOG_ERROR("Encryption failed: 0x%x", result);
    }
    
    free(ciphertext);
    return result;
}

static int handle_decrypt(daemon_context_t *ctx, const sdfx_decrypt_req_t *req,
                         sdfx_decrypt_resp_t *resp)
{
    LOG_DEBUG("Handling decrypt request");
    
    HANDLE session_handle = req->session_handle;
    ULONG alg_id = sdfx_ntohl(req->alg_id);
    ULONG iv_length = sdfx_ntohl(req->iv_length);
    ULONG enc_data_length = sdfx_ntohl(req->enc_data_length);
    
    LOG_DEBUG("Decrypt: session=0x%lx, alg=0x%lx, iv_len=%lu, enc_len=%lu", 
             (unsigned long)session_handle, (unsigned long)alg_id, 
             (unsigned long)iv_length, (unsigned long)enc_data_length);
    
    /* Validate session */
    uint32_t session_id = (uint32_t)(uintptr_t)session_handle;
    int ret_validate = session_manager_validate_session(ctx, session_id);
    if (ret_validate != SDR_OK) {
        LOG_ERROR("Invalid session handle: 0x%lx", (unsigned long)session_handle);
        return SDR_SESSION_NOT_EXIST;
    }
    
    /* Extract IV and ciphertext data */
    const BYTE *iv = (iv_length > 0) ? req->payload : NULL;
    const BYTE *ciphertext = req->payload + iv_length;
    
    /* For demonstration purposes, use a fixed key (should be managed by key handle in practice) */
    BYTE key[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
                    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10};
    
    /* Allocate output buffer */
    ULONG max_plaintext_len = enc_data_length + 16; /* extra space */
    BYTE *plaintext = malloc(max_plaintext_len);
    if (plaintext == NULL) {
        LOG_ERROR("Failed to allocate plaintext buffer: %s", strerror(errno));
        return SDR_NOBUFFER;
    }
    
    /* Call symmetric decryption function */
    ULONG plaintext_len = max_plaintext_len;
    int result = crypto_symmetric_decrypt(alg_id, key, sizeof(key), iv, iv_length,
                                        ciphertext, enc_data_length, plaintext, &plaintext_len);
    
    if (result == SDR_OK) {
        /* Convert plaintext length to network byte order and copy data */
        resp->data_length = sdfx_htonl(plaintext_len);
        memcpy(resp->data, plaintext, plaintext_len);
        LOG_DEBUG("Decryption successful, output length: %lu", (unsigned long)plaintext_len);
    } else {
        LOG_ERROR("Decryption failed: 0x%x", result);
    }
    
    free(plaintext);
    return result;
}

/**
 * @brief Handle SM2 key pair generation request
 */
static int handle_generate_keypair_ecc(daemon_context_t *ctx,
                                      const sdfx_generate_keypair_ecc_req_t *req,
                                      sdfx_generate_keypair_ecc_resp_t *resp)
{
    if (req == NULL || resp == NULL) {
        return SDR_INARGERR;
    }
    
    LOG_DEBUG("Handling ECC key pair generation request");
    
    /* Validate algorithm ID */
    ULONG alg_id = sdfx_ntohl(req->alg_id);
    if (alg_id != SGD_SM2_1) {
        LOG_ERROR("Unsupported algorithm ID: 0x%lx", alg_id);
        return SDR_NOTSUPPORT;
    }
    
    /* Generate SM2 key pair */
    int result = crypto_sm2_generate_keypair(&resp->public_key, &resp->private_key);
    
    if (result == SDR_OK) {
        LOG_DEBUG("SM2 key pair generated successfully");
    } else {
        LOG_ERROR("SM2 key pair generation failed: 0x%x", result);
    }
    
    return result;
}

/**
 * @brief Handle external SM2 encryption request
 */
static int handle_external_encrypt_ecc(daemon_context_t *ctx,
                                      const sdfx_external_encrypt_ecc_req_t *req,
                                      sdfx_external_encrypt_ecc_resp_t *resp)
{
    if (req == NULL || resp == NULL) {
        return SDR_INARGERR;
    }
    
    LOG_DEBUG("Handling external ECC encrypt request");
    
    /* Validate algorithm ID */
    ULONG alg_id = sdfx_ntohl(req->alg_id);
    if (alg_id != SGD_SM2_1) {
        LOG_ERROR("Unsupported algorithm ID: 0x%lx", alg_id);
        return SDR_NOTSUPPORT;
    }
    
    ULONG data_length = sdfx_ntohl(req->data_length);
    if (data_length == 0 || data_length > 256) {
        LOG_ERROR("Invalid data length: %lu", data_length);
        return SDR_INARGERR;
    }
    
    /* Perform SM2 encryption */
    ULONG cipher_len = sizeof(resp->cipher.C);
    int result = crypto_sm2_external_encrypt(&req->public_key, req->data, data_length,
                                           resp->cipher.C, &cipher_len);
    
    if (result == SDR_OK) {
        resp->cipher.L = sdfx_htonl(cipher_len);
        LOG_DEBUG("SM2 encryption completed: %lu bytes -> %lu bytes", data_length, cipher_len);
    } else {
        LOG_ERROR("SM2 encryption failed: 0x%x", result);
    }
    
    return result;
}

/**
 * @brief Handle external SM2 decryption request
 */
static int handle_external_decrypt_ecc(daemon_context_t *ctx,
                                      const sdfx_external_decrypt_ecc_req_t *req,
                                      sdfx_external_decrypt_ecc_resp_t *resp)
{
    if (req == NULL || resp == NULL) {
        return SDR_INARGERR;
    }
    
    LOG_DEBUG("Handling external ECC decrypt request");
    
    /* Validate algorithm ID */
    ULONG alg_id = sdfx_ntohl(req->alg_id);
    if (alg_id != SGD_SM2_1) {
        LOG_ERROR("Unsupported algorithm ID: 0x%lx", alg_id);
        return SDR_NOTSUPPORT;
    }
    
    ULONG cipher_len = sdfx_ntohl(req->cipher.L);
    if (cipher_len == 0 || cipher_len > sizeof(req->cipher.C)) {
        LOG_ERROR("Invalid cipher length: %lu", cipher_len);
        return SDR_INARGERR;
    }
    
    /* Perform SM2 decryption */
    ULONG plaintext_len = 256;  /* maximum plaintext length */
    int result = crypto_sm2_external_decrypt(&req->private_key, req->cipher.C, cipher_len,
                                           resp->data, &plaintext_len);
    
    if (result == SDR_OK) {
        resp->data_length = sdfx_htonl(plaintext_len);
        LOG_DEBUG("SM2 decryption completed: %lu bytes -> %lu bytes", cipher_len, plaintext_len);
    } else {
        LOG_ERROR("SM2 decryption failed: 0x%x", result);
    }
    
    return result;
}

/**
 * @brief Handle external SM2 signing request
 */
static int handle_external_sign_ecc(daemon_context_t *ctx,
                                   const sdfx_external_sign_ecc_req_t *req,
                                   sdfx_external_sign_ecc_resp_t *resp)
{
    if (req == NULL || resp == NULL) {
        return SDR_INARGERR;
    }
    
    LOG_DEBUG("Handling external ECC sign request");
    
    /* Validate algorithm ID */
    ULONG alg_id = sdfx_ntohl(req->alg_id);
    if (alg_id != SGD_SM2_3) {  /* SM2 signature algorithm */
        LOG_ERROR("Unsupported algorithm ID: 0x%lx", alg_id);
        return SDR_NOTSUPPORT;
    }
    
    ULONG data_length = sdfx_ntohl(req->data_length);
    if (data_length == 0) {
        LOG_ERROR("Invalid data length: %lu", data_length);
        return SDR_INARGERR;
    }
    
    /* Perform SM2 signing */
    ULONG signature_len = 128;  /* SM2 signature maximum length */
    int result = crypto_sm2_external_sign(&req->private_key, req->data, data_length,
                                        resp->signature, &signature_len);
    
    if (result == SDR_OK) {
        resp->signature_length = sdfx_htonl(signature_len);
        LOG_DEBUG("SM2 signature completed: %lu bytes data -> %lu bytes signature", 
                  data_length, signature_len);
    } else {
        LOG_ERROR("SM2 signature failed: 0x%x", result);
    }
    
    return result;
}

/**
 * @brief Handle external SM2 verification request
 */
static int handle_external_verify_ecc(daemon_context_t *ctx,
                                     const sdfx_external_verify_ecc_req_t *req,
                                     sdfx_external_verify_ecc_resp_t *resp)
{
    if (req == NULL || resp == NULL) {
        return SDR_INARGERR;
    }
    
    LOG_DEBUG("Handling external ECC verify request");
    
    /* Validate algorithm ID */
    ULONG alg_id = sdfx_ntohl(req->alg_id);
    if (alg_id != SGD_SM2_3) {  /* SM2 signature algorithm */
        LOG_ERROR("Unsupported algorithm ID: 0x%lx", alg_id);
        return SDR_NOTSUPPORT;
    }
    
    ULONG data_length = sdfx_ntohl(req->data_length);
    ULONG signature_length = sdfx_ntohl(req->signature_length);
    
    if (data_length == 0 || signature_length == 0) {
        LOG_ERROR("Invalid lengths - data: %lu, signature: %lu", data_length, signature_length);
        return SDR_INARGERR;
    }
    
    /* Get data and signature pointers */
    const BYTE *data = req->payload;
    const BYTE *signature = req->payload + data_length;
    
    /* Perform SM2 verification */
    int result = crypto_sm2_external_verify(&req->public_key, data, data_length,
                                          signature, signature_length);
    
    /* Set verification result */
    resp->result = sdfx_htonl((result == SDR_OK) ? 0 : 1);
    
    if (result == SDR_OK) {
        LOG_DEBUG("SM2 verification succeeded");
    } else {
        LOG_DEBUG("SM2 verification failed: 0x%x", result);
        result = SDR_OK;  /* Verification failure is not an error, distinguished by the result field */
    }
    
    return result;
}

int protocol_handler_init(daemon_context_t *ctx)
{
    LOG_INFO("Protocol handler initialized");
    return SDR_OK;
}

void protocol_handler_cleanup(daemon_context_t *ctx)
{
    LOG_INFO("Protocol handler cleanup completed");
}

int protocol_handler_process_message(daemon_context_t *ctx,
                                    const sdfx_message_t *request,
                                    sdfx_message_t **response,
                                    size_t *response_size)
{
    if (ctx == NULL || request == NULL || response == NULL || response_size == NULL) {
        return SDR_INARGERR;
    }
    
    ULONG result = SDR_OK;
    size_t resp_data_size = 0;
    
    /* Get command from network byte order */
    ULONG cmd = sdfx_ntohl(request->header.cmd);
    
    LOG_DEBUG("Processing command %lu", (unsigned long)cmd);
    ctx->total_requests++;
    
    /* Determine response data size based on command type */
    switch (cmd) {
        case SDFX_CMD_OPEN_DEVICE:
            resp_data_size = sizeof(sdfx_open_device_resp_t);
            break;
        case SDFX_CMD_CLOSE_DEVICE:
            resp_data_size = sizeof(sdfx_close_device_resp_t);
            break;
        case SDFX_CMD_OPEN_SESSION:
            resp_data_size = sizeof(sdfx_open_session_resp_t);
            break;
        case SDFX_CMD_CLOSE_SESSION:
            resp_data_size = sizeof(sdfx_close_session_resp_t);
            break;
        case SDFX_CMD_GET_DEVICE_INFO:
            resp_data_size = sizeof(sdfx_get_device_info_resp_t);
            break;
        case SDFX_CMD_GENERATE_RANDOM: {
            const sdfx_generate_random_req_t *req = (const sdfx_generate_random_req_t *)request->data;
            ULONG length = sdfx_ntohl(req->length);
            resp_data_size = sizeof(sdfx_generate_random_resp_t) + length;
            break;
        }
        case SDFX_CMD_HASH_INIT:
            resp_data_size = 0;  // No response data
            break;
        case SDFX_CMD_HASH_UPDATE:
            resp_data_size = 0;  // No response data
            break;
        case SDFX_CMD_HASH_FINAL:
            resp_data_size = sizeof(sdfx_hash_final_resp_t) + 64;  // maximum hash length
            break;
        case SDFX_CMD_ENCRYPT: {
            const sdfx_encrypt_req_t *req = (const sdfx_encrypt_req_t *)request->data;
            ULONG data_length = sdfx_ntohl(req->data_length);
            resp_data_size = sizeof(sdfx_encrypt_resp_t) + data_length + 32;  // Reserve space for padding
            break;
        }
        case SDFX_CMD_DECRYPT: {
            const sdfx_decrypt_req_t *req = (const sdfx_decrypt_req_t *)request->data;
            ULONG enc_data_length = sdfx_ntohl(req->enc_data_length);
            resp_data_size = sizeof(sdfx_decrypt_resp_t) + enc_data_length + 16;  // Reserve space
            break;
        }
        case SDFX_CMD_GENERATE_KEYPAIR_ECC:
            resp_data_size = sizeof(sdfx_generate_keypair_ecc_resp_t);
            break;
        case SDFX_CMD_EXTERNAL_ENCRYPT_ECC: {
            const sdfx_external_encrypt_ecc_req_t *req = (const sdfx_external_encrypt_ecc_req_t *)request->data;
            ULONG data_length = sdfx_ntohl(req->data_length);
            resp_data_size = sizeof(sdfx_external_encrypt_ecc_resp_t);
            break;
        }
        case SDFX_CMD_EXTERNAL_DECRYPT_ECC: {
            const sdfx_external_decrypt_ecc_req_t *req = (const sdfx_external_decrypt_ecc_req_t *)request->data;
            resp_data_size = sizeof(sdfx_external_decrypt_ecc_resp_t) + 256;  // Reserve space for decryption
            break;
        }
        case SDFX_CMD_EXTERNAL_SIGN_ECC: {
            resp_data_size = sizeof(sdfx_external_sign_ecc_resp_t) + 128;  // SM2 signature length
            break;
        }
        case SDFX_CMD_EXTERNAL_VERIFY_ECC:
            resp_data_size = sizeof(sdfx_external_verify_ecc_resp_t);
            break;
        default:
            LOG_WARN("Unknown command %lu", (unsigned long)cmd);
            result = SDR_NOTSUPPORT;
            resp_data_size = 0;
            break;
    }
    
    /* Allocate response message with bounds check */
    if (resp_data_size > SDFX_MAX_MESSAGE_SIZE - sizeof(sdfx_message_header_t)) {
        LOG_ERROR("Response data too large: %zu bytes (max: %lu)",
                 resp_data_size, 
                 (unsigned long)(SDFX_MAX_MESSAGE_SIZE - sizeof(sdfx_message_header_t)));
        return SDR_NOBUFFER;
    }
    
    *response_size = sizeof(sdfx_message_header_t) + resp_data_size;
    *response = malloc(*response_size);
    if (*response == NULL) {
        LOG_ERROR("Failed to allocate response message: %s", strerror(errno));
        return SDR_NOBUFFER;
    }
    
    memset(*response, 0, *response_size);
    (*response)->header.magic = sdfx_htonl(SDFX_MAGIC);
    (*response)->header.version = sdfx_htonl(SDFX_PROTOCOL_VERSION);  /* Add version number */
    (*response)->header.cmd = request->header.cmd;
    (*response)->header.length = sdfx_htonl(resp_data_size);
    (*response)->header.session_id = request->header.session_id;
    
    /* Process command */
    if (result == SDR_OK) {
        switch (cmd) {
            case SDFX_CMD_OPEN_DEVICE:
                result = handle_open_device(ctx,
                    (const sdfx_open_device_req_t *)request->data,
                    (sdfx_open_device_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_CLOSE_DEVICE:
                result = handle_close_device(ctx,
                    (const sdfx_close_device_req_t *)request->data,
                    (sdfx_close_device_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_OPEN_SESSION:
                result = handle_open_session(ctx,
                    (const sdfx_open_session_req_t *)request->data,
                    (sdfx_open_session_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_CLOSE_SESSION:
                result = handle_close_session(ctx,
                    (const sdfx_close_session_req_t *)request->data,
                    (sdfx_close_session_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_GET_DEVICE_INFO:
                result = handle_get_device_info(ctx,
                    (const sdfx_get_device_info_req_t *)request->data,
                    (sdfx_get_device_info_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_GENERATE_RANDOM:
                result = handle_generate_random(ctx,
                    (const sdfx_generate_random_req_t *)request->data,
                    (sdfx_generate_random_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_HASH_INIT:
                result = handle_hash_init(ctx,
                    (const sdfx_hash_init_req_t *)request->data,
                    (sdfx_hash_init_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_HASH_UPDATE:
                result = handle_hash_update(ctx,
                    (const sdfx_hash_update_req_t *)request->data,
                    (sdfx_hash_update_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_HASH_FINAL:
                result = handle_hash_final(ctx,
                    (const sdfx_hash_final_req_t *)request->data,
                    (sdfx_hash_final_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_ENCRYPT:
                result = handle_encrypt(ctx,
                    (const sdfx_encrypt_req_t *)request->data,
                    (sdfx_encrypt_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_DECRYPT:
                result = handle_decrypt(ctx,
                    (const sdfx_decrypt_req_t *)request->data,
                    (sdfx_decrypt_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_GENERATE_KEYPAIR_ECC:
                result = handle_generate_keypair_ecc(ctx,
                    (const sdfx_generate_keypair_ecc_req_t *)request->data,
                    (sdfx_generate_keypair_ecc_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_EXTERNAL_ENCRYPT_ECC:
                result = handle_external_encrypt_ecc(ctx,
                    (const sdfx_external_encrypt_ecc_req_t *)request->data,
                    (sdfx_external_encrypt_ecc_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_EXTERNAL_DECRYPT_ECC:
                result = handle_external_decrypt_ecc(ctx,
                    (const sdfx_external_decrypt_ecc_req_t *)request->data,
                    (sdfx_external_decrypt_ecc_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_EXTERNAL_SIGN_ECC:
                result = handle_external_sign_ecc(ctx,
                    (const sdfx_external_sign_ecc_req_t *)request->data,
                    (sdfx_external_sign_ecc_resp_t *)(*response)->data);
                break;
                
            case SDFX_CMD_EXTERNAL_VERIFY_ECC:
                result = handle_external_verify_ecc(ctx,
                    (const sdfx_external_verify_ecc_req_t *)request->data,
                    (sdfx_external_verify_ecc_resp_t *)(*response)->data);
                break;
        }
    }
    
    (*response)->header.status = sdfx_htonl(result);
    
    LOG_DEBUG("Command %lu processed, result = %ld", (unsigned long)cmd, result);
    return result;
}